package com.duke.shaking.interaction;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.duke.shaking.R;
import com.duke.shaking.ShakeTabActivity;
import com.duke.shaking.TitleActivity;
import com.duke.shaking.net.MessageFetcher;
import com.duke.shaking.net.MessageSender;
import com.duke.shaking.net.MessageFetcher.MessageFetchListener;
import com.duke.shaking.net.MessageSender.MessageSendListener;
import com.duke.shaking.pojo.ChatFriend;
import com.duke.shaking.pojo.Message;
import com.duke.shaking.profile.FriendProfileActivity;
import com.duke.shaking.storage.DataManager;
import com.duke.shaking.widget.ResizeLinearLayout;
import com.duke.shaking.widget.ResizeLinearLayout.OnResizeListener;

public class ChatActivity extends TitleActivity
		implements MessageFetchListener, 
		OnItemLongClickListener, 
		MessageSendListener,
		OnResizeListener,
		OnScrollListener {

	private ChatFriend friend;
	private ListView lst_messages;
	private List<Message> messages;
	private EditText edit_message;
	private MessagesListAdapter adapter;
	private ResizeLinearLayout layout_chat;
	
	//private MessageFetcher msgFetcher;
	private int readMsgPerLoad = 20;
	private int unreadMsgPerLoad = -1; // unlimit
	private boolean isFirstSend;
	private Handler handler;
	private int topVisiblePosition;
	private int bottomVisiblePosition;
	private View view_lstHeader;
	private boolean isLoading;
	private HandlerThread loadMsgHandlerThread;
	private LoadMsgHandler loadMsgHandler;
	
	public void onCreate(Bundle savedInstanceState) {
		info("ChatActivity.onCreate");
        super.onCreate(savedInstanceState);
        isFirstSend = true;
        friend = (ChatFriend)getIntent().getSerializableExtra("friend");
        
        messages = loadMessages(friend, readMsgPerLoad, -1, false);
        adapter = new MessagesListAdapter(this, messages);
        
        topVisiblePosition = -1;
        bottomVisiblePosition = -1;
        
        lst_messages = (ListView)findViewById(R.id.lst_messages);
        //lst_messages.setOnItemLongClickListener(this);
        view_lstHeader = LayoutInflater.from(this).inflate(R.layout.view_msg_list_header, null);
        lst_messages.addHeaderView(view_lstHeader);
        view_lstHeader.setVisibility(View.GONE);
        lst_messages.setAdapter(adapter);
        if (messages.size() > 0) {
        	lst_messages.setSelection(messages.size() - 1);
        }

        lst_messages.setOnScrollListener(this);
        
        edit_message = (EditText)findViewById(R.id.edit_message);
        
        layout_chat = (ResizeLinearLayout)findViewById(R.id.layout_chat);
        layout_chat.setOnResizeListener(this);
        handler = new Handler();
        
		MessageSender.getShared().addListener(this);
		if (loadMsgHandlerThread == null) {
			loadMsgHandlerThread = new HandlerThread("loadMsgThread");
			loadMsgHandlerThread.start();
			loadMsgHandler = new LoadMsgHandler(loadMsgHandlerThread.getLooper());
		}
        
	}
	
	protected void onStart() {
		super.onStart();
		onNewMessageArrived();
		MessageFetcher.getShared().addListener(this);
	}
	
	protected void onStop() {
		super.onStop();
		MessageFetcher.getShared().removeListener(this);
	}
	
	protected void onDestroy() {
		super.onDestroy();
		MessageSender.getShared().removeListener(this);
		if (loadMsgHandlerThread != null) {
			loadMsgHandler = null;
			loadMsgHandlerThread.quit();
			loadMsgHandlerThread = null;
		}
		
	}

	private List<Message> loadMessages(ChatFriend friend, 
			int loadCount, long maxMsgId, boolean onlyRead) {
		isLoading = true;
		try {
			List<Message> null_msgs = new ArrayList<Message>();
			if (friend == null) {
				return null_msgs;
			}
			
			DataManager dm = DataManager.getShared();
			List<Message> msgs = dm.loadReadMessagesByFriendId(
					friend.getUserId(), loadCount, maxMsgId);
			
			if (msgs == null) {
				msgs = null_msgs;
			}
			if (!onlyRead) {
				List<Message> unreadMsgs = dm.loadUnreadMessagesByFriendId(
					friend.getUserId(), unreadMsgPerLoad);
				if (unreadMsgs != null && unreadMsgs.size() > 0) {
					msgs.addAll(unreadMsgs);
				}
			}
			return msgs;
		}
		finally {
			isLoading = false;
		}
		
	}
	
	@Override
	protected int getLayoutId() {
		// TODO Auto-generated method stub
		return R.layout.activity_chat;
	}

	@Override
	protected void onTitleInit() {
		// TODO Auto-generated method stub
		initTitle(ShakeTabActivity.TITLE_BTN_EXIST | ShakeTabActivity.TITLE_BTN_BACK,
				R.string.message,
				ShakeTabActivity.TITLE_BTN_EXIST,
				R.string.look_profile,
				0);
	}

	public void onRightBtn(View v) {
		// TODO Auto-generated method stub
		go(FriendProfileActivity.class, "friend", friend);
	}

	public void onSendBtn(View v) {
		if (edit_message == null) {
			return;
		}
		String txt = edit_message.getText().toString();
		if (txt == null || txt.equals("")) {
			return;
		}
		if (friend == null || me == null || !me.hasLogin()) {
			return;
		}
		
		Message msg = new Message();
		msg.setContent(txt);
		msg.setDirection(Message.MSG_DIRECTION_TO);
		msg.setToId(friend.getUserId());
		
		msg.setFromId(me.getUserId());
		msg.setUnread(false);
		msg.setSendState(Message.SEND_STATE_SENDING);
		msg.setTimestamp(new Date());
		msg.setRecvTime(new Date());
		if (isFirstSend) {
			if (DataManager.getShared().getFriendById(friend.getUserId()) == null) {
				DataManager.getShared().putOrUpdateFriend(friend);
			}
			isFirstSend = false;
		}
		long msgId = DataManager.getShared().putMessage(msg);
		if (msgId < 0) {
			toast("");
			return;
		}
		
		msg.setMsgId(msgId);
		messages.add(msg);
		edit_message.setText("");
		
		adapter.notifyDataSetChanged();
		lst_messages.setSelection(lst_messages.getCount() - 1);
		
		MessageSender.getShared().sendMsg(msg);
	}

	public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
			   long id) {
		
		return false;
	}

	public void onNewMessageArrived() {
		// TODO Auto-generated method stub
		boolean scrollToBottom = false;
		
		List<Message> msgs = DataManager.getShared().loadUnreadMessagesByFriendId(
				friend.getUserId(), unreadMsgPerLoad);
		if (msgs == null) {
			return;
		}
		if (lst_messages.getLastVisiblePosition() >= lst_messages.getCount() - 1) {
			scrollToBottom = true;
		}
		for (Message msg : msgs) {
			messages.add(msg);
		}
		
		adapter.notifyDataSetChanged();
		if (scrollToBottom) {
			lst_messages.setSelection(lst_messages.getCount() - 1);
		}
		
	}

	public void onMessageSent(Message msg, boolean success) {
		// TODO Auto-generated method stub
		int index = messages.lastIndexOf(msg);
		if (index >= 0) {
			adapter.notifyDataSetChanged();
		}
	}

	private class ListViewSelRunnable implements Runnable {

		public void run() {
			if (lst_messages != null && lst_messages.getCount() > 0) {
				lst_messages.setSelection(lst_messages.getCount() - 1);
			}
		}
		
	}
	
	private class ListViewReloadedRunnable implements Runnable {
		private List<Message> newMsgs;
		
		public ListViewReloadedRunnable(List<Message> newMsgs) {
			this.newMsgs = newMsgs;
		}
		
		public void run() {
			view_lstHeader.setVisibility(View.GONE);
			if (newMsgs == null || newMsgs.size() <= 0) {
				return;
			}
			int currSelPosition = newMsgs.size() - 1;
			messages.addAll(0, newMsgs);
			adapter.notifyDataSetChanged();
			if (lst_messages != null 
				&& currSelPosition >= 0 
				&& currSelPosition < lst_messages.getCount()) {
				lst_messages.setSelection(currSelPosition);
			}
			
		}
		
	}
	
	private class LoadMsgHandler extends Handler {
        
		public boolean stoped;
		
        public LoadMsgHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(android.os.Message msg) {
            synchronized (this) {
            	if (stoped) {
            		return;
            	}
            	long currMinMsgId = -1;
            	if (messages != null && messages.size() > 0) {
            		Message topMsg = messages.get(0);
            		if (topMsg != null && topMsg.getMsgId() != null) {
            			currMinMsgId = topMsg.getMsgId();
            		}
            	}
            	List<Message> msgs = loadMessages(friend, 
            			readMsgPerLoad, currMinMsgId, true);
            	if (stoped) {
            		return;
            	}
            	handler.post(new ListViewReloadedRunnable(msgs));
            }
        }
    }
	
	public void OnResize(int w, int h, int oldw, int oldh) {
		
		if (lst_messages != null) {
			if (messages.size() > 0) {
				handler.post(new ListViewSelRunnable());
			}
		}
		
	}

	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		// TODO Auto-generated method stub
		topVisiblePosition = firstVisibleItem;
		bottomVisiblePosition = firstVisibleItem + visibleItemCount - 1;
	}

	public void onScrollStateChanged(AbsListView view, int scrollState) {
		// TODO Auto-generated method stub
		if (topVisiblePosition == 0 && scrollState == SCROLL_STATE_IDLE) {
			if (loadMsgHandler != null && !isLoading) {
				view_lstHeader.setVisibility(View.VISIBLE);
				loadMsgHandler.sendEmptyMessageDelayed(0, 300);
			}
		}
	}
}
